package com.chinadrtv.batch.admin.controller.ozing;

import com.chinadrtv.batch.admin.service.OzingCardBatchService;
import com.chinadrtv.batch.admin.util.Constants;
import com.chinadrtv.user.model.CardType;
import com.chinadrtv.user.model.OzingCard;
import com.chinadrtv.user.model.OzingCardBatch;
import com.chinadrtv.user.model.User;
import com.chinadrtv.user.service.UserManager;
import com.chinadrtv.user.service.ozing.OzingCardService;
import com.chinadrtv.user.service.ozing.OzingService;
import com.chinadrtv.user.util.CardUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * User: ping.chen
 */

@Controller
public class OzingCardJobController {
    private static final Log log = LogFactory.getLog(OzingCardJobController.class.getName());
    final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
    final static SimpleDateFormat yyyyMMdd_sf = new SimpleDateFormat("yyMMdd");


    @Autowired
    private OzingService ozingService;

    @Autowired
    private OzingCardService ozingCardService;

    @Autowired
    private OzingCardBatchService ozingCardBatchService;

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private UserManager userManager;

    @Autowired
    private Job triggerCardJob;




    @RequestMapping(value = "/ozing/cards/present", method = RequestMethod.GET)
    public String triggerCards() {
        return "/ozing/present_cards";
    }

    @RequestMapping(value = "/ozing/cards/present", method = RequestMethod.POST)
    public String triggerCardsJob(HttpServletRequest request, HttpServletResponse response,
                            @RequestParam(required = true) String cardValue,@RequestParam(required = true) String period,
                            @RequestParam(required = true) String periodType,@RequestParam(required = true) String cardType,
                           @RequestParam(required = false) String description,
                           @RequestParam(required = true) String usernames, @RequestParam(required = false) String deviceNumber) throws ParseException, JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, IOException {
        String[] us = usernames.split(",");
        StringBuilder sb = new StringBuilder();
        int length = us.length;
        for (int i = 0; i < length; i++) {
            if (i == length - 1) {
                sb.append("'");
                sb.append(us[i]);
                sb.append("'");
            } else {
                sb.append("'");
                sb.append(us[i]);
                sb.append("'");
                sb.append(",");
            }
        }


        User user = getCurrentUser(request);
        List<User> users = userManager.findByUserNames(sb.toString());
        if(users.size()<=0){
            response.setContentType("text/json; charset=UTF-8");
            response.getWriter().write("{\"error\":true}");
        }

        ozingCardService.handlePresentCardProcess(users, cardValue,period,periodType, cardType,description,usernames,deviceNumber);

        return null;
    }

    @RequestMapping(value = "/ozing/card/job/init", method = RequestMethod.POST)
    public @ResponseBody
    Object initCard(HttpServletRequest request, HttpServletResponse response,
                           @RequestParam(required = true) String quantity, @RequestParam(required = true) String cardValue,
                           @RequestParam(required = true) String period, @RequestParam(required = true) String periodType,
                           @RequestParam(required = true) String deadline,@RequestParam(required = true) String cardType,
                           @RequestParam(required = false) String description, @RequestParam(required = false) String cardSalePrice ) throws ParseException, JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        User user = getCurrentUser(request);
        //
        int cardIndex = ozingCardService.getTodayCardIndex();
        if(cardIndex>99999){
            return false;
        }

        JobParametersBuilder builder = new JobParametersBuilder();

        builder.addString("quantity", quantity);
        builder.addLong("cardValue", Long.valueOf(cardValue));
        builder.addLong("cardSalePrice", Long.valueOf(cardSalePrice));
        builder.addString("period", period);
        builder.addString("periodType", periodType);
        builder.addDate("deadline", sf.parse(deadline));
        builder.addDate("date", new Date());
        builder.addString("cardType", cardType);
        builder.addString("description", description);

       OzingCardBatch ozingCardBatch = ozingCardBatchService.handleTriggerCardJob(builder, user);
        //execute triggerCardJob
        builder.addLong("batchId",ozingCardBatch.getId());
        JobExecution jobExecution = jobLauncher.run(triggerCardJob, builder.toJobParameters());

        //update executionId and instanceId
        ozingCardBatch.setExecutionId(jobExecution.getId());
        ozingCardBatch.setInstanceId(jobExecution.getJobInstance().getId());
        ozingCardBatchService.update(ozingCardBatch);

        return true;
    }

    @RequestMapping(value = "/ozing/job/trigger", method = RequestMethod.GET)
    public String initManualJob(HttpServletRequest request, HttpServletResponse response) {
        return "/ozing/job_trigger";
    }

    @RequestMapping(value = "/ozing/card/job/delivery", method = RequestMethod.POST)
    public String delivery(HttpServletRequest request, HttpServletResponse response,
                           @RequestParam(required = true) String agent, @RequestParam(required = true) String batchId,
                           @RequestParam(required = true) String cardIndexStart, @RequestParam(required = true) String cardIndexEnd){
        ozingCardService.delivery(Long.valueOf(batchId), OzingCard.CardStatus.DELIVERED,
                Integer.valueOf(cardIndexStart), Integer.valueOf(cardIndexEnd), agent);
        return null;
    }

    @RequestMapping(value = "/ozing/card/job/status", method = RequestMethod.POST)
    public String updateStatus(HttpServletRequest request, HttpServletResponse response,
                           @RequestParam(required = true) String status, @RequestParam(required = true) String batchId,
                           @RequestParam(required = true) String cardIndexStart, @RequestParam(required = true) String cardIndexEnd){
        ozingCardService.updateStatus(Long.valueOf(batchId), OzingCard.CardStatus.valueOf(status),
                Integer.valueOf(cardIndexStart), Integer.valueOf(cardIndexEnd));
        return null;
    }

    @RequestMapping(value = "/ozing/job/cards", method = RequestMethod.GET)
    public String jobCards() {
        return "/ozing/job_cards";
    }

    @RequestMapping(value = "/ozing/job/cards.json", method = RequestMethod.GET)
    public String jobCardsJson(HttpServletRequest request, HttpServletResponse response,
                               @RequestParam(required = false, defaultValue = "0") String start_index, @RequestParam(required = false, defaultValue = "30") String num_per_page,
                               @RequestParam(required = true) String batchId) throws IOException, ParseException {
        JSONArray jsonArray = new JSONArray();
        List<OzingCard> ozingCards = new ArrayList<OzingCard>();
        int totalRecords = 0;
        if (batchId != null && !batchId.trim().equals("")) {
            ozingCards = ozingService.getOzingCardListByBatch(Integer.valueOf(start_index), Integer.valueOf(num_per_page), Long.valueOf(batchId));

            for (OzingCard ozingCard : ozingCards) {
                JSONObject jsonObject = ozingCard.toJson();
                jsonArray.put(jsonObject);
            }
            totalRecords = ozingService.countOzingCardByBatch(Long.valueOf(batchId));
        }

        response.setContentType("text/json; charset=UTF-8");
        response.getWriter().write("{\"records\":" + jsonArray.toString() + ",\"totalRecords\":" + totalRecords + ",\"startIndex\":" + start_index + "}");
        return null;
    }


    private User getCurrentUser(HttpServletRequest request) {
        SecurityContext ctx = (SecurityContext) request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
        return (User) ctx.getAuthentication().getPrincipal();
    }
}
